/**
 * @p.md
 * 
 * LocalContext 提供本地 Actor 的上下文实现
 */
import { ActorContext } from './actorContext';
import { Actor } from './actor';
import { PID } from './pid';
import { ActorSystem } from './actorSystem';
import { ActorProcess } from './actorProcess';
import { Mailbox, MessageQueue } from './mailbox';
import { Props } from './props';
import { DefaultMailbox } from './defaultMailbox';
import { DefaultMessageQueue } from './mailbox';
import * as SystemMessages from './systemMessages';
import { Dispatcher } from './dispatcher';
import { Supervisor } from './supervision';
import { EventStream, Events } from './eventStream';
import { MessageInvoker } from './messageInvoker';

/**
 * LocalContext 类，管理本地 Actor 的生命周期和消息处理
 */
export class LocalContext extends ActorContext {
  private _mailbox: Mailbox;
  private _process: ActorProcess;
  private _supervisor: any; // 使用 any 类型暂时绕过类型检查
  private _dispatcher: any; // 使用 any 类型暂时绕过类型检查
  private _isStarted: boolean = false;
  private _isStopped: boolean = false;
  private _watchers: Set<PID> = new Set();
  private _watching: Set<PID> = new Set();

  /**
   * 构造函数
   * @param actor Actor 实例
   * @param props Actor 属性
   * @param parent 父 Actor 的 PID
   * @param system Actor 系统
   * @param id Actor ID
   */
  constructor(
    actor: Actor,
    private readonly _props: Props,
    parent: PID | null,
    system: ActorSystem,
    id: string
  ) {
    // 创建 PID 并初始化基类
    const address = system.processRegistry.address();
    const self = new PID(address, id);
    super(actor, self, parent, system);

    // 获取监督策略和调度器
    this._supervisor = _props.supervisor;
    this._dispatcher = _props.dispatcher || {/* 默认调度器 */};

    // 创建邮箱
    let userMailbox: Mailbox;
    if (_props.mailboxProducer) {
      userMailbox = _props.mailboxProducer();
    } else {
      // 创建默认邮箱
      const userQueue = new DefaultMessageQueue();
      const systemQueue = new DefaultMessageQueue();
      userMailbox = new DefaultMailbox(userQueue, systemQueue);
    }
    this._mailbox = userMailbox;

    // 创建 Actor 进程
    this._process = new ActorProcess(this._mailbox);

    // 注册进程
    system.processRegistry.add(this._process, id);
  }

  /**
   * 设置 Actor 实例
   * @param actor 新的 Actor 实例
   */
  setActor(actor: Actor): void {
    // @ts-ignore - 虽然父类没有这个字段的公开访问器，但我们知道它存在
    this._actor = actor;
  }

  /**
   * 发送系统消息的公开方法
   * @param target 目标 PID
   * @param message 系统消息
   */
  protected sendSystemMessagePublic(target: PID, message: any): void {
    const process = this.actorSystem().processRegistry.get(target);
    if (process) {
      process.sendSystemMessage(target, message);
    }
  }

  /**
   * 启动 Actor
   */
  start(): void {
    if (this._isStarted) {
      return;
    }

    this._isStarted = true;
    
    // 发布 Actor 启动事件
    this.actorSystem().eventStream.publish(new Events.ActorStarted(this.self()));
    
    // 发送启动消息
    this.sendSystemMessagePublic(this.self(), new SystemMessages.Started());
  }

  /**
   * 停止 Actor
   */
  stopActor(): void {
    if (this._isStopped) {
      return;
    }

    this._isStopped = true;
    
    // 停止所有子 Actor
    for (const child of this.children()) {
      this.stop(child);
    }
    
    // 取消监视的 Actor
    for (const watched of this._watching) {
      this.unwatch(watched);
    }
    
    // 通知所有监视者当前 Actor 已终止
    for (const watcher of this._watchers) {
      this.sendSystemMessagePublic(watcher, new SystemMessages.Terminated(this.self()));
    }
    
    // 发布 Actor 停止事件
    this.actorSystem().eventStream.publish(new Events.ActorStopped(this.self()));
    
    // 从 ProcessRegistry 中移除
    this.actorSystem().processRegistry.remove(this.self());
  }

  /**
   * 重启 Actor
   * @param reason 重启原因
   */
  restartActor(reason: Error): void {
    if (this._isStopped) {
      return;
    }
    
    // 发布 Actor 重启事件
    this.actorSystem().eventStream.publish(new Events.ActorRestarted(this.self(), reason));
    
    // 停止所有子 Actor
    for (const child of this.children()) {
      this.stop(child);
    }
    
    // 创建新的 Actor 实例
    const actor = this._props.producer();
    this.setActor(actor);
    
    // 发送重启消息
    this.sendSystemMessagePublic(this.self(), new SystemMessages.Restart(reason));
  }

  /**
   * 添加监视者
   * @param watcher 监视者 PID
   */
  addWatcher(watcher: PID): void {
    if (this._isStopped) {
      // 如果 Actor 已停止，直接发送终止消息
      this.sendSystemMessagePublic(watcher, new SystemMessages.Terminated(this.self()));
      return;
    }
    
    this._watchers.add(watcher);
  }

  /**
   * 移除监视者
   * @param watcher 监视者 PID
   */
  removeWatcher(watcher: PID): void {
    this._watchers.delete(watcher);
  }

  /**
   * 添加被监视的 Actor
   * @param pid 被监视的 Actor PID
   */
  addWatching(pid: PID): void {
    this._watching.add(pid);
  }

  /**
   * 移除被监视的 Actor
   * @param pid 被监视的 Actor PID
   */
  removeWatching(pid: PID): void {
    this._watching.delete(pid);
  }

  /**
   * 处理 Actor 失败
   * @param reason 失败原因
   * @param message 导致失败的消息
   */
  handleFailure(reason: Error, message: any): void {
    if (this.parent()) {
      // 将失败上报给父 Actor
      const failure = new SystemMessages.Failure(this.self(), reason);
      this.sendSystemMessagePublic(this.parent()!, failure);
    } else {
      // 顶级 Actor 使用监督策略处理失败
      // 使用简化版本的调用
      if (typeof this._supervisor.handleFailure === 'function') {
        this._supervisor.handleFailure(this.self(), reason);
      }
    }
  }

  /**
   * 获取调度器
   */
  get dispatcher(): any {
    return this._dispatcher;
  }
  
  /**
   * 获取监督策略
   */
  get supervisor(): any {
    return this._supervisor;
  }
  
  /**
   * 检查 Actor 是否已停止
   */
  get isStopped(): boolean {
    return this._isStopped;
  }
}

/**
 * LocalContext 工厂类
 */
export const LocalContexts = {
  /**
   * 创建一个新的 LocalContext
   * @param actor Actor 实例
   * @param props Actor 属性
   * @param parent 父 Actor
   * @param system Actor 系统
   * @param id Actor ID
   * @returns LocalContext 实例
   */
  create(
    actor: Actor,
    props: Props,
    parent: PID | null,
    system: ActorSystem,
    id: string
  ): LocalContext {
    return new LocalContext(actor, props, parent, system, id);
  }
}; 